const runMicroTask = (cb: () => void) => {
  if (
    typeof globalThis.process !== "undefined" &&
    typeof globalThis.process.nextTick === "function"
  ) {
    process.nextTick(cb);
  } else if (globalThis.MutationObserver) {
    const p = document.createElement("p");
    const observer = new MutationObserver(cb);
    observer.observe(p, {
      childList: true, // 观察该元素内部的变化
    });
    p.innerHTML = "1";
  } else {
    setTimeout(cb, 0);
  }
};

const isPromise = (obj: any) => {
  return !!(
    obj &&
    typeof obj === "object" &&
    obj.then &&
    typeof obj.then === "function"
  );
};

type StateType = "pending" | "fulfilled" | "rejected";
type ValueType = any;

type ResolveType = (data: any) => void;
type RejectType = (reason: any) => void;
type ExecutorType = (resolve: ResolveType, reject: RejectType) => void;

type HanlderType = {
  state: StateType;
  resolve: ResolveType;
  reject: RejectType;
  executor?: ResolveType | RejectType;
};

class MyPromise {
  state: StateType = "pending";
  value: ValueType = void 0;
  private _handlers: HanlderType[] = [];

  private _changeState(newState: StateType, newValue: ValueType) {
    if (this.state !== "pending") return;
    this.state = newState;
    this.value = newValue;
    this._runHandlers();
  }

  private _resolve(data: any) {
    this._changeState("fulfilled", data);
  }

  private _reject(reason: any) {
    this._changeState("rejected", reason);
  }

  private _pushHandler(
    state: StateType,
    resolve: ResolveType,
    reject: RejectType,
    executor?: ResolveType | RejectType
  ) {
    const handler: HanlderType = {
      state,
      resolve,
      reject,
      executor,
    };
    this._handlers.push(handler);
  }

  private _runOneHandler(handler: HanlderType) {
    runMicroTask(() => {
      if (this.state !== handler.state) return;
      if (typeof handler.executor !== "function") {
        this.state === "fulfilled"
          ? handler.resolve(this.value)
          : handler.reject(this.value);
        return;
      }
      try {
        const executor = handler.executor;
        const res = executor(this.value);
        // 返回是一个promise，此时promise的状态受返回的promise控制
        if (isPromise(res)) {
          (res as unknown as Promise<any>).then(
            handler.resolve,
            handler.reject
          );
        } else handler.resolve(res);
      } catch (erro) {
        handler.reject(erro);
      }
    });
  }

  private _runHandlers() {
    if (this.state === "pending") return;
    while (this._handlers[0]) {
      this._runOneHandler(this._handlers[0]);
      this._handlers.shift();
    }
  }

  then(onFulfilled?: ResolveType, onRejected?: RejectType) {
    return new MyPromise((resolve, reject) => {
      this._pushHandler("fulfilled", resolve, reject, onFulfilled);
      this._pushHandler("rejected", resolve, reject, onRejected);
      this._runHandlers();
    });
  }

  constructor(executor: ExecutorType) {
    executor(this._resolve.bind(this), this._reject.bind(this));
  }
}

const p = new MyPromise((resolve, reject) => {
  //   resolve(123);
  //   reject(888);

  setTimeout(() => {
    resolve(123);
  });
});
p.then(
  function A1() {},
  function A2() {}
);
p.then(
  function B1() {},
  function B2() {}
);

setTimeout(() => {
  console.log(p);
}, 400);
